package 题目集.线段树or树状数组.线段树;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.PrintWriter;
import java.io.StreamTokenizer;

/**
 * https://www.luogu.com.cn/problem/P3372
 */
public class ch01_增加模板 {
    static int maxN = (int) (1e5 + 10);
    static int tMaxN = (int) Math.pow(2, Math.ceil(Math.log(maxN) / Math.log(2)) + 1);
    static int[] src;
    static Node[] tree;
    static int n, m, tn;    //tn是树实际的最大长度

    public static void main(String[] args) {
        Reader2 sc = new Reader2(System.in);
        n = sc.nextInt();
        m = sc.nextInt();
        src = new int[n + 1];
        for (int i = 1; i <= n; i++) {
            src[i] = sc.nextInt();
        }
        init();
        for (int i = 0; i < m; i++) {
            int op = sc.nextInt();
            int l = sc.nextInt();
            int r = sc.nextInt();
            if (op == 1) {
                int v = sc.nextInt();
                add(1, l, r, v);
            } else {
                long query = query(1, l, r);
                Reader2.pw.println(query);
            }
        }
        Reader2.pw.flush();
    }

    public static void init() {
        tn = (int) Math.pow(2, Math.ceil(Math.log(n) / Math.log(2)) + 1);
        tree = new Node[tn];
        build(1, 1, n);
    }

    public static void build(int i, int l, int r) {
        tree[i] = new Node(l, r);
        if (l == r) {
            tree[i].val = src[l];
        } else {
            int m = l + r >> 1;
            build(i << 1, l, m);
            build(i << 1 | 1, m + 1, r);
            pull(i);
        }
    }

    /**
     * @param i：区间的下标
     * @param l-r：操作的区间
     * @param v：值
     */
    public static void add(int i, int l, int r, long v) {
        if (l <= tree[i].l && tree[i].r <= r) {
            addLazy(i, v);
            return;
        }
        push(i);
        int m = tree[i].l + tree[i].r >> 1;
        if (l <= m) {
            add(i << 1, l, r, v);
        }
        if (m < r) {
            add(i << 1 | 1, l, r, v);
        }
//        tree[i].val += (r - l + 1) * v;   //可能是 l,r与tree[i]相交，而不是包含lr，所以这里不行
        pull(i);
    }

    public static long query(int i, int l, int r) {
        if (l <= tree[i].l && tree[i].r <= r) {
            return tree[i].val;
        }
        push(i);
        int m = tree[i].l + tree[i].r >> 1;
        long res = 0;
        if (l <= m) {
            res += query(i << 1, l, r);
        }
        if (m < r) {
            res += query(i << 1 | 1, l, r);
        }
        return res;
    }

    /**
     * 每一个非叶子节点一定是孩子双全的，调用pull的只会是非叶子节点，所以无需判断左右孩子是否越界。
     */
    public static void pull(int i) {
        tree[i].val = tree[i << 1].val + tree[i << 1 | 1].val;
    }

    /**
     * 与pull相同，会调用此方法的都是非叶子节点，左右孩子都存在
     */
    public static void push(int i) {
        if (tree[i].addTask == 0) return;
        addLazy(i << 1, tree[i].addTask);
        addLazy(i << 1 | 1, tree[i].addTask);
        tree[i].addTask = 0;
    }

    public static void addLazy(int i, long v) {
        tree[i].val += tree[i].len * v;
        tree[i].addTask += v;
    }

    static class Node {
        int l, r;
        int len;
        long val;
        long addTask;

        public Node(int l, int r) {
            this.l = l;
            this.r = r;
            len = r - l + 1;
        }

        @Override
        public String toString() {
            return "Node{" +
                    "l=" + l +
                    ", r=" + r +
                    ", len=" + len +
                    ", val=" + val +
                    ", addTask=" + addTask +
                    '}';
        }
    }

    static class Reader2 {
        static StreamTokenizer in = new StreamTokenizer(new BufferedInputStream(System.in));
        static PrintWriter pw = new PrintWriter(new BufferedOutputStream(System.out));

        public Reader2(Object... o) {
        }

        public int nextInt() {
            try {
                in.nextToken();
            } catch (Exception ignored) {
            }
            return (int) in.nval;
        }
    }

}
